<?php

declare(strict_types=1);

namespace App\Dao;

use App\Model\CityIp;
use App\Model\User;
use App\Utils\LoggerUtil;
use App\Utils\ToolUtil;
use Hyperf\Context\ApplicationContext;

class CityIpDao
{
    private static $instance;

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = Applicationcontext::getcontainer()->get(self::class);
        }
        return self::$instance;
    }

    public function getProvinceCity($ip, $userInfo = array())
    {
        if (!empty($userInfo)) {
            if (!empty($userInfo['ext2'])) {
                $userInfo['ext2'] = !is_object($userInfo['ext2']) ? json_decode($userInfo['ext2']) : $userInfo['ext2'];
                if (isset($userInfo['ext2']->province) && $userInfo['ext2']->province && $userInfo['ext2']->city) {
                    $retval['province'] = $userInfo['ext2']->province;
                    $retval['city'] = $userInfo['ext2']->city;
                }
            }
            if (empty($retval) && !empty($userInfo['ext'])) {
                $userInfo['ext'] = !is_object($userInfo['ext']) ? json_decode($userInfo['ext']) : $userInfo['ext'];
                if (isset($userInfo['ext']->location) && $userInfo['ext']->location) {
                    $res = $this->getDataWithLocation($userInfo['ext']->location);
                    if ($res['province'] && $res['city']) {
                        $userInfo['ext2']->province = $retval['province'] = $res['province'];
                        $userInfo['ext2']->city = $retval['city'] = $res['city'];
                        User::query()->where('id', $userInfo['id'])->update(
                            ['ext2' => json_encode($userInfo['ext2'])]
                        );
                        // Mem::delete("userInfo_".$userInfo['id']);
                    }
                }
            }
            if (empty($retval)) {
                $retval = $this->getDataWithIp($ip);
            }
        } else {
            $retval = $this->getDataWithIp($ip);
        }
        return $retval;
    }


    public function getDataWithLocation($location)
    {
        $retval['province'] = '';
        $retval['city'] = '';
        if ($location->lat && $location->lng) {
            $lat = $location->lat; //纬度
            $lng = $location->lng; //经度
            $loc = $lat . "," . $lng;
            $api_url = "http://api.map.baidu.com/geocoder/v2/?ak=avG2C8Mqh6RqB7SVpx1KgNqLG1NEsxyf&location={$loc}&output=json";
            $result = file_get_contents($api_url);
            $result = json_decode($result, true);
            if ($result['status'] == 0 && !empty($result['result']['addressComponent'])) {
                $retval['country'] = $result['result']['addressComponent']['country'];
                $retval['province'] = self::processWholeProvince($result['result']['addressComponent']['province']);
                $retval['city'] = (string)$result['result']['addressComponent']['city'];

                //把诸如"广州市"后面的市字去掉，统一
                if (!empty($retval['province'])) {
                    if (!empty($retval['city'])) {

                        empty($_tmp['city']) && $_tmp['city'] = $retval['city'];
                    } else {
                        $_tmp['city'] = '';
                    }
                } else {
                    $_tmp['city'] = '';
                }
                $retval['city'] = $_tmp['city'];
            }
        }

        return $retval;
    }

    public function getDataWithIp($ip)
    {
        if ($ip == 'Unknow') {
            return array('province' => '', 'city' => '');
        }
        $_ip = sprintf("%u", ip2long($ip));
        // $ipcache = Mem::get('user_ip2long_'.$_ip);
        $ipcache = false;
        if ($ipcache === false) {
            $rs = CityIp::query()->where('start_ip', '<=', $_ip)->where('end_ip', '>=', $_ip)->limit(5)->get();
            $ipcache = array();
            if ($rs->isNotEmpty()) {
                foreach ($rs as $v) {
                    $country = $v['country'];
                    $province = $v['province'];
                    $lng = $v['lng'];
                    $lat = $v['lat'];
                    if (strpos($v['city'], '/') !== false) {
                        $pos = mb_strpos($v['city'], '/', 0, 'utf8');
                        $city = mb_substr($v['city'], 0, $pos, 'utf-8');
                        break;
                    } elseif (strpos($v['city'], '(') !== false) {
                        $pos = mb_strpos($v['city'], '(', 0, 'utf8');
                        if ($pos > 0) {
                            $city = mb_substr($v['city'], 0, $pos, 'utf-8');
                            break;
                        }
                    } elseif ($v['city'] === null) {
                        continue;
                    } else {
                        $city = $v['city'];
                        break;
                    }
                }
                $ipcache['country'] = $country;
                $ipcache['province'] = $province;
                $ipcache['city'] = $city ?? '';
                $ipcache['lng'] = $lng ?? 0;
                $ipcache['lat'] = $lat ?? 0;
            } else {
                $ip_section3_start = $_ip - $_ip % 256;
                $ip_section3_end = $ip_section3_start + 255;

                $url = "https://ipcity.market.alicloudapi.com/ip/city/query?coordsys=coordsys&ip=$ip";
                $header = ['Authorization:APPCODE b7b0751b55fc403a8f28b92e05abcfdf'];
                $result = ToolUtil::api_curl($url, null, $header);
                LoggerUtil::write("getDataWithIp", $result);
                $_result = json_decode($result, true);
                if ($_result['code'] == 200) {
                    $ipcache['country'] = $_result['data']['result']['country'] ?? '';
                    $ipcache['province'] = self::processWholeProvince($_result['data']['result']['prov']);
                    $ipcache['city'] = $_result['data']['result']['city'] ?? '';

                    $ipcache['lng'] = $_result['data']['result']['lng'];
                    $ipcache['lat'] = $_result['data']['result']['lat'];

                    if ($ipcache['province'] && $ipcache['city']) {
                        $insert_data = array(
                            "start_ip" => $ip_section3_start,
                            "end_ip" => $ip_section3_end,
                            "country" => $ipcache['country'],
                            "province" => $ipcache['province'],
                            "city" => $ipcache['city'],
                            "isp" => '',
                            "start_ip1" => long2ip($ip_section3_start),
                            "end_ip1" => long2ip($ip_section3_end),
                            "lng" => $ipcache['lng'],
                            "lat" => $ipcache['lat']
                        );
                        // Tool::log2("getDataWithIp.txt", $insert_data, $ip);
                        CityIp::query()->insert($insert_data);
                    } else {
                        $ipcache['country'] = '';
                        $ipcache['province'] = '';
                        $ipcache['city'] = '';
                        $ipcache['lng'] = 0;
                        $ipcache['lat'] = 0;
                    }
                } else {
                    $ipcache['country'] = '';
                    $ipcache['province'] = '';
                    $ipcache['city'] = '';
                    $ipcache['lng'] = 0;
                    $ipcache['lat'] = 0;
                }
                LoggerUtil::write("getDataWithIp", $_ip . ':' . json_encode($ipcache));
            }

            //把诸如"广州市"后面的市字去掉，统一
            if (!empty($ipcache['province'])) {
                if (!empty($ipcache['city'])) {
                    empty($_tmp['city']) && $_tmp['city'] = $ipcache['city'];
                } else {
                    $_tmp['city'] = '';
                }
            } else {
                $_tmp['city'] = '';
            }
            $ipcache['city'] = $_tmp['city'];
            // Mem::set('user_ip2long_'.$_ip, $ipcache, 300);
        }

        if (empty($ipcache['province']) || empty($ipcache['city'])) {
            LoggerUtil::write("getDataWithIp", json_encode($ipcache));
        }

        return $ipcache;
    }

    public static function processWholeProvince($p)
    {
        $array = array(
            '北京市' => '北京',
            '天津市' => '天津',
            '河北省' => '河北',
            '山西省' => '山西',
            '内蒙古自治区' => '内蒙古',
            '辽宁省' => '辽宁',
            '吉林省' => '吉林',
            '黑龙江省' => '黑龙江',
            '上海市' => '上海',
            '江苏省' => '江苏',
            '浙江省' => '浙江',
            '安徽省' => '安徽',
            '福建省' => '福建',
            '江西省' => '江西',
            '山东省' => '山东',
            '河南省' => '河南',
            '湖北省' => '湖北',
            '湖南省' => '湖南',
            '广东省' => '广东',
            '广西壮族自治区' => '广西',
            '海南省' => '海南',
            '重庆市' => '重庆',
            '四川省' => '四川',
            '贵州省' => '贵州',
            '云南省' => '云南',
            '西藏自治区' => '西藏',
            '陕西省' => '陕西',
            '甘肃省' => '甘肃',
            '青海省' => '青海',
            '宁夏回族自治区' => '宁夏',
            '新疆维吾尔自治区' => '新疆',
            '香港特别行政区' => '香港',
            '澳门特别行政区' => '澳门',
            '台湾省' => '台湾'
        );
        return !empty($array[$p]) ? $array[$p] : $p;
    }

}